#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#define NFRAMES  1000


inline int64_t get_time_duration(struct timeval *ctime, struct timeval *ltime)
{
    int64_t duration;
    duration = (ctime->tv_sec - ltime->tv_sec) * 1000000;
    duration += ctime->tv_usec - ltime->tv_usec;
    return duration;
}

typedef struct {
    struct timeval *in_time;
    struct timeval *out_time;
    int64_t    frame_in_cnt;
    int64_t    frame_out_cnt;
} latency_context_t;


inline latency_context_t* latency_init(void)
{
    latency_context_t* p_lc = (latency_context_t*)calloc(1,sizeof(latency_context_t));

    p_lc->frame_in_cnt = 0;
    p_lc->frame_out_cnt =0;

    p_lc->in_time = (timeval*)calloc(NFRAMES, sizeof(struct timeval));
    p_lc->out_time = (timeval*)calloc(NFRAMES, sizeof(struct timeval));

    return p_lc;
}
inline void latency_frame_in(latency_context_t* p_lc) {
    if(p_lc != 0) {
        gettimeofday(p_lc->in_time + p_lc->frame_in_cnt%NFRAMES, NULL);
        p_lc->frame_in_cnt++;
    }

}
inline void latency_frame_out(latency_context_t* p_lc) {
    if(p_lc != 0) {
       gettimeofday(p_lc->out_time + p_lc->frame_out_cnt%NFRAMES, NULL);
       p_lc->frame_out_cnt++;
    }
}
inline int latency_print_statistic(latency_context_t* p_lc) {
    int64_t frame_index;
    int64_t latency = 0;

    frame_index = p_lc->frame_out_cnt-1;
    if(p_lc != 0) {

        if (frame_index < 0) {
            latency = 0;
            av_log(NULL, AV_LOG_INFO, " latency=0ms \n");
        }
        if(frame_index%NFRAMES>0) {
            latency = get_time_duration(p_lc->out_time+frame_index%NFRAMES, p_lc->in_time+frame_index%NFRAMES)/1000;
            av_log(NULL, AV_LOG_INFO, " latency=%ldms \n", latency);
        } else {
            latency = get_time_duration(p_lc->out_time,p_lc->in_time)/1000;
            av_log(NULL, AV_LOG_INFO, " latency=%3ldms \n", latency);
        }
    }
    return latency;
}
inline void latency_free(latency_context_t* p_lc)
{
    if(p_lc !=0) {
        if(p_lc->in_time) {
            free(p_lc->in_time);
        }
        if(p_lc->out_time) {
            free(p_lc->out_time);
        }
        free(p_lc);
    }
    
}

